home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / GDEVCDJ.C < prev    next >
C/C++ Source or Header  |  1992-03-25  |  10KB  |  353 lines

  1. /*
  2.  * Copyright (C) 1991, 1992 Aladdin Enterprises.  All rights reserved.
  3.  * Distributed by Free Software Foundation, Inc.
  4.  * 
  5.  * This file is part of Ghostscript.
  6.  * 
  7.  * Ghostscript is distributed in the hope that it will be useful, but WITHOUT
  8.  * ANY WARRANTY.  No author or distributor accepts responsibility to anyone
  9.  * for the consequences of using it or for whether it serves any particular
  10.  * purpose or works at all, unless he says so in writing.  Refer to the
  11.  * Ghostscript General Public License for full details.
  12.  * 
  13.  * Everyone is granted permission to copy, modify and redistribute Ghostscript,
  14.  * but only under the conditions described in the Ghostscript General Public
  15.  * License.  A copy of this license is supposed to have been given to you
  16.  * along with Ghostscript so you can know your rights and responsibilities.
  17.  * It should be in a file named COPYING.  Among other things, the copyright
  18.  * notice and this notice must be preserved on all copies.
  19.  */
  20.  
  21. /* gdevcdj.c */
  22. /* H-P DeskJet 500C driver (colour) for Ghostscript */
  23. #include "gdevprn.h"
  24. #include "gdevpcl.h"
  25.  
  26. /***
  27.  *** Note: this driver was contributed by a user, George Cameron:
  28.  ***       please contact g.cameron@aberdeen.ac.uk if you have questions.
  29.  ***/
  30.  
  31. /*
  32.  *   Definitions affecting print quality/speed
  33.  */
  34.  
  35. /* #define A4               * .. if in Europe */
  36. #ifndef SHINGLING        /* Interlaced, multi-pass printing */
  37. #define SHINGLING 1      /* 0 = none, 1 = 50%, 2 = 25%, 2 is best & slowest */
  38. #endif
  39.  
  40. #ifndef DEPLETION        /* 'Intelligent' dot-removal */
  41. #define DEPLETION 1      /* 0 = none, 1 = 25%, 2 = 50%, 1 best for graphics? */
  42. #endif                   /* Use 0 for transparencies */
  43.  
  44. /*
  45.  * You may select a resolution of 75, 100, 150, or 300 DPI.
  46.  * Normally you would do this in the makefile or on the gs command line,
  47.  * not here.
  48.  */
  49.  
  50. #define X_DPI_MAX 300
  51. #define Y_DPI_MAX 300
  52.  
  53. #ifndef X_DPI
  54. #  define X_DPI X_DPI_MAX
  55. #endif
  56. #ifndef Y_DPI
  57. #  define Y_DPI Y_DPI_MAX
  58. #endif
  59.  
  60. /* We round up LINE_SIZE to a multiple of 8 bytes */
  61. /* because that's the unit of transposition from pixels to planes. */
  62. #define LINE_SIZE ((X_DPI_MAX * 85 / 10 + 63) / 64 * 8)
  63.  
  64. /* For all DeskJet Printers:
  65.  *
  66.  *  Maximum printing width               = 2400 dots = 8"
  67.  *  Maximum printing height (colour)     = 3100 dots = 10.3"
  68.  *                          (monochrome) = 3150 dots = 10.5"
  69.  *  All Deskjets have 1/2" unprintable bottom margin
  70.  */
  71. #ifndef A4
  72. #define PAPER_SIZE 2       /* US Letter is default size */
  73. #define WIDTH_10THS 85
  74. #define HEIGHT_10THS 110
  75. #define L_MARGIN 0.25
  76. #define B_MARGIN 0.5
  77. #define R_MARGIN 0.25
  78. #define T_MARGIN 0.2
  79. #else
  80. #define PAPER_SIZE 26      /* A4 size normal in Europe */
  81. #define WIDTH_10THS 83     /* 210mm */
  82. #define HEIGHT_10THS 117   /* 297mm */
  83. #define L_MARGIN 0.134
  84. #define B_MARGIN 0.7
  85. #define R_MARGIN 0.134
  86. #define T_MARGIN 0.66
  87. #endif
  88.  
  89. /* The device descriptor */
  90. private         dev_proc_print_page(cdeskjet_print_page);
  91. private gx_device_procs cdeskjet_procs =
  92. prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
  93.         gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb);
  94.     gx_device_printer gs_cdeskjet_device =
  95.     prn_device(cdeskjet_procs, "cdeskjet",
  96.            WIDTH_10THS, HEIGHT_10THS,
  97.            X_DPI, Y_DPI,
  98.            L_MARGIN, R_MARGIN, T_MARGIN, B_MARGIN,
  99.            3, cdeskjet_print_page);
  100.  
  101. /* Forward references */
  102. private int gdev_pcl_mode9compress(P4(int, const byte *, byte *, byte *));
  103.  
  104. /* ------ Internal routines ------ */
  105.  
  106. /* Send the page to the printer.  Compress each scan line. */
  107. private int
  108. cdeskjet_print_page(gx_device_printer *pdev, FILE *prn_stream)
  109. {
  110. #define DATA_SIZE (LINE_SIZE * 8)
  111.     byte  data[DATA_SIZE];
  112.     byte  plane_data[3][LINE_SIZE], prev_plane_data[3][LINE_SIZE];
  113.     int   x_dpi = pdev->x_pixels_per_inch;
  114.  
  115.     /* Initialize printer. */
  116.     fputs("\033E", prn_stream);        /* reset printer */
  117.  
  118.     /* ends raster graphics to set raster graphics resolution */
  119.     fputs("\033*rbC", prn_stream);
  120.  
  121.     /* set raster graphics resolution -- 75, 100, 150 or300 dpi */
  122.     fprintf(prn_stream, "\033*t%dR", x_dpi);
  123.  
  124.     /* set the line width */
  125.     fprintf(prn_stream, "\033*r%dS", DATA_SIZE);
  126.  
  127.     /* paper size, orientation, perf skip, feed from tray*/ 
  128.     fprintf(prn_stream, "\033&l%da0o0l1H", PAPER_SIZE);
  129.  
  130.     /* set the number of color planes */
  131.     fprintf(prn_stream, "\033*r-%dU", 3);    /* always 3, -ve for CMY */
  132.  
  133.     /* set depletion level */
  134.     fprintf(prn_stream, "\033*o%dD", DEPLETION);
  135.  
  136.     /* set shingling level */
  137.     fprintf(prn_stream, "\033*o%dQ", SHINGLING);
  138.  
  139.     /* move to top left of page */
  140.     fputs("\033&a0H\033&a0V", prn_stream);
  141.  
  142.     /* select data compression */
  143.     fputs("\033*b9M", prn_stream);              /* mode 9 */
  144.  
  145.     /* start raster graphics */
  146.     fputs("\033*r1A", prn_stream);
  147.  
  148.     bzero(&prev_plane_data[0][0], LINE_SIZE * 3);
  149.  
  150.     /* Send each scan line in turn */
  151.     {
  152.     int  lnum;
  153.     int  line_size = gdev_prn_bytes_per_scan_line(pdev);
  154.     int  line_count = line_size / pdev->color_info.depth;
  155.     int  num_blank_lines = 0;
  156.  
  157.     for (lnum = 0; lnum < pdev->height; lnum++) {
  158.         byte _ss *end_data = data + line_size;
  159.         gdev_prn_copy_scan_lines(pdev, lnum,
  160.                      (byte *) data, line_size);
  161.         /* Remove trailing 0s. */
  162.         while (end_data > data && end_data[-1] == 0)
  163.         end_data--;
  164.         if (end_data == data) {    /* Blank line */
  165.         num_blank_lines++;
  166.         } else {
  167.         int             i;
  168.         byte _ss       *odp;
  169.  
  170.         /* Pad with 0s to fill out the last */
  171.         /* block of 8 bytes. */
  172.         memset(end_data, 0, 7);
  173.  
  174.         /* Transpose the data to get pixel planes. */
  175.         for (i = 0, odp = &plane_data[0][0]; i < DATA_SIZE;
  176.              i += 8, odp++
  177.             ) {        /* The following is for 16-bit machines */
  178. #define spread3(c)\
  179.  { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L }
  180.             static ulong    spr40[8] = spread3(0x40);
  181.             static ulong    spr8[8] = spread3(8);
  182.             static ulong    spr2[8] = spread3(2);
  183.             register byte _ss *dp = data + i;
  184.             register ulong  pword =
  185.             (spr40[dp[0]] << 1) +
  186.             (spr40[dp[1]]) +
  187.             (spr40[dp[2]] >> 1) +
  188.             (spr8[dp[3]] << 1) +
  189.             (spr8[dp[4]]) +
  190.             (spr8[dp[5]] >> 1) +
  191.             (spr2[dp[6]]) +
  192.             (spr2[dp[7]] >> 1);
  193.             odp[0] = (byte) (pword >> 16);
  194.             odp[LINE_SIZE] = (byte) (pword >> 8);
  195.             odp[LINE_SIZE * 2] = (byte) (pword);
  196.         }
  197.         /* Skip blank lines if any */
  198.         if (num_blank_lines > 0) {    /* move down from current
  199.                          * position */
  200.             fprintf(prn_stream, "\033&a+%dV",
  201.                 num_blank_lines * (720 / Y_DPI));
  202.             num_blank_lines = 0;
  203.             bzero(&prev_plane_data[0][0], LINE_SIZE * 3);
  204.         }
  205.         /* Transfer raster graphics */
  206.         /* in the order C, M, Y. */
  207.         for (i = 0; i < 3; i++) {
  208.  
  209.             byte temp[LINE_SIZE * 2];
  210.  
  211.             int count = gdev_pcl_mode9compress(line_count,
  212.                                plane_data[2 - i],
  213.                                prev_plane_data[2 - i],
  214.                                temp);
  215.  
  216.             fprintf(prn_stream, "\033*b%d%c", count, "VVW"[i]);
  217.             fwrite(temp, sizeof(byte), count, prn_stream);
  218.         }
  219.         }
  220.     }
  221.     }
  222.  
  223.     /* end raster graphics */
  224.     fputs("\033*rbC", prn_stream);
  225.  
  226.     /* reset to monochrome */
  227.     fputs("\033*r1U", prn_stream);
  228.  
  229.     /* eject page */
  230.     fputs("\033&l0H", prn_stream);
  231.  
  232.     return 0;
  233. }
  234.  
  235. private int
  236. gdev_pcl_mode9compress(int bytecount, const byte *current, byte *previous, byte *compressed)
  237. {
  238.   register const byte *cur = current;
  239.   register byte *prev = previous;
  240.   register byte *out = compressed;
  241.   const byte *end = current + bytecount;
  242.  
  243.   while ( cur < end )
  244.     {    /* Detect a run of unchanged bytes. */
  245.       const byte *run = cur;
  246.       register const byte *diff;
  247.       int offset;
  248.       while ( cur < end && *cur == *prev )
  249.     {    cur++, prev++;
  250.     }
  251.       if ( cur == end ) break;    /* rest of row is unchanged */
  252.       /* Detect a run of changed bytes. */
  253.       /* We know that *cur != *prev. */
  254.       diff = cur;
  255.       do
  256.     {    *prev++ = *cur++;
  257.     }
  258.       while ( cur < end && *cur != *prev );
  259.       /* Now [run..diff) are unchanged, and */
  260.       /* [diff..cur) are changed. */
  261.       offset = diff - run;
  262.       {
  263.     const byte  *stop_test = cur - 4;
  264.     int   dissimilar, similar;
  265.     
  266.     while (diff < cur) {
  267.       const byte *compr = diff;
  268.       const byte *next;    /* end of run */
  269.       byte value;
  270.       while (diff <= stop_test &&
  271.          ((value = *diff) != diff[1] ||
  272.           value != diff[2] ||
  273.           value != diff[3]))
  274.         diff++;
  275.       
  276.       /* Find out how long the run is */
  277.       if (diff > stop_test)    /* no run */
  278.         next = diff = cur;
  279.       else {
  280.         next = diff + 4;
  281.         while (next < cur && *next == value)
  282.           next++;
  283.       }
  284.       
  285. #define MAXOFFSETU 15
  286. #define MAXCOUNTU 7
  287.       /* output 'dissimilar' bytes, uncompressed */
  288.       if ((dissimilar = diff - compr))
  289.         {
  290.           int temp, i;
  291.  
  292.           if ((temp = --dissimilar) > MAXCOUNTU) temp = MAXCOUNTU;
  293.           if (offset < MAXOFFSETU)
  294.         *out++ = (offset << 3) | (byte)temp;
  295.           else {
  296.         *out++ = (MAXOFFSETU << 3) | (byte)temp;
  297.         offset -= MAXOFFSETU;
  298.         while (offset >= 255) {
  299.           *out++ = 255;
  300.           offset -= 255;
  301.         }
  302.         *out++ = offset;
  303.           }
  304.           if (temp == MAXCOUNTU) {
  305.         temp = dissimilar - MAXCOUNTU;
  306.         while (temp >= 255) {
  307.           *out++ = 255;
  308.           temp -= 255;
  309.         }
  310.         *out++ = (byte)temp;
  311.           }
  312.           for (i = 0; i <= dissimilar; i++) *out++ = *compr++;
  313.           offset = 0;
  314.         } /* end uncompressed */
  315.       
  316. #define MAXOFFSETC 3
  317. #define MAXCOUNTC 31
  318.       /* output 'similar' bytes, run-length endcoded */
  319.       if ((similar = next - diff))
  320.         {
  321.           int temp;
  322.  
  323.           if ((temp = (similar -= 2)) > MAXCOUNTC) temp = MAXCOUNTC;
  324.           if (offset < MAXOFFSETC)
  325.         *out++ = 0x80 | (offset << 5) | (byte)temp;
  326.           else {
  327.         *out++ = 0x80 | (MAXOFFSETC << 5) | (byte)temp;
  328.         offset -= MAXOFFSETC;
  329.         while (offset >= 255) {
  330.           *out++ = 255;
  331.           offset -= 255;
  332.         }
  333.         *out++ = offset;
  334.           }
  335.           if (temp == MAXCOUNTC) {
  336.         temp = similar - MAXCOUNTC;
  337.         while (temp >= 255) {
  338.           *out++ = 255;
  339.           temp -= 255;
  340.         }
  341.         *out++ = (byte)temp;
  342.           }
  343.           *out++ = value;
  344.           offset = 0;
  345.         } /* end compressed */
  346.       
  347.       diff = next;
  348.     }
  349.       }
  350.     }
  351.   return out - compressed;
  352. }
  353.